home *** CD-ROM | disk | FTP | other *** search
/ 1,000+ Great Games / 1_1000 Games.iso / DOSGAMES / POLYINIT.ZIP / GRAPH.C next >
Encoding:
C/C++ Source or Header  |  1995-08-28  |  22.7 KB  |  1,340 lines

  1. #pragma inline
  2. #include <stdio.h>
  3. #include <alloc.h>
  4. #include <dos.h>
  5. #include <process.h>
  6.  
  7. #include "y_off.h"
  8.  
  9. //*************************RUTINAS NUEVAS******************************
  10. //************REQUIEREN OPTIMZACIαN A NIVEL DE ENSAMBLADOR*************
  11. //MACROS ΘTILES
  12. #define ABS(a)   ((a < 0) ? -a : a)
  13. #define SGN(a)   ((a < 0) ? -1 : 1)
  14. #define XCHG(a,b,c) ((c=a),(a=b),(b=c))
  15. #define OFFS(x,y) (y_off[y]+x)
  16.  
  17.  
  18. typedef struct
  19. {
  20.     int x,y,z;
  21. } VERTEX_3D;
  22.  
  23. int getoff(void);
  24. int valloc( unsigned long asize );
  25. void vfree( int segm );
  26.  
  27. int array_flag=0, dbg_cnt;
  28. int SCRN=0xA000;
  29. int far *x_array, far *closed_ptr;
  30. unsigned int w_array, closed;
  31. extern int old_mode;
  32.  
  33. //    Función: _putpixel
  34. //  Pone el pixel de la pantalla del color especificado
  35. void putpixel( int x, int y, int color)
  36. {   unsigned int off;
  37.     asm{
  38.         mov ax,x
  39.         mov bx,y
  40.     };
  41.     getoff();
  42.     asm{
  43.         mov di,ax
  44.         mov ax,0A000h
  45.         mov es,ax
  46.         mov ax,color
  47.         stosb
  48.     };
  49. }
  50.  
  51. //linea entre (x1,y1) y (x2,y2), del color especificado.
  52. void linea( int x1, int y1, int x2, int y2, int color )
  53. {    unsigned int frac, xac, pre_xac, absdx, absdy;
  54.     int intg, x, y, dy, dx;
  55.     unsigned long acum, delta;
  56.  
  57.     dx=1;
  58.     dy=1;
  59.  
  60.     if(x1>x2)
  61.         dx=-1;
  62.  
  63.     if(y1>y2)
  64.         dy=-1;
  65.  
  66.     acum= (long) (ABS((x2-x1)));
  67.     acum<<=16;
  68.     delta=(long) (ABS((y2-y1)));
  69.     if(delta==0L)
  70.         dy=0;
  71.     else
  72.         delta=acum/delta;
  73.     frac=(int) (delta&0xFFFFL);
  74.     intg=(int) (delta>>16);
  75.     if(dx<1)
  76.         intg=-intg;
  77.     x=x1;
  78.     y=y1;
  79.     xac=frac;
  80.     do{
  81.         putpixel( x, y, color);
  82.         y+=dy;
  83.         pre_xac=xac;
  84.         xac+=frac;
  85.         if(xac<pre_xac)
  86.             x+=dx;
  87.         x+=intg;
  88.     }while(y!=y2);
  89.     putpixel( x2, y2, color );
  90. }
  91.  
  92. /*
  93.     Para que la función de sombreado interpolativo funcione, es necesario
  94.     que haya un apartado en la paleta de 16 colores (en esta primera fase)
  95.     que contenga una gama de colores (desde intensidad 0, hasta casi blanco
  96.     del mismo color). comenzarán en el color designado por el parámetro
  97.     así llamado, en cuyo lugar se encontrará el mas obscuro de ellos, a
  98.     continuación se irá incrementando la intensidad del color hasta el
  99.     máximo (luminosidad del 80% ). a futuro es posible efectuar el sombreado
  100.     de forma que la paleta corresponda con la intensidad relativa del color
  101.     para un sombreado entero, ajustando la paleta cada vez que sea necesario.
  102.     igualmente, ajustando el gradiente de intensidad. Incluso tal vez sea
  103.     posible que los colores utilizados no tengan un número fijo, sino que
  104.     sean variables de acuerdo a lo necesario.
  105. */
  106.  
  107. int colr[2048];
  108. int MAX_COL=84;
  109. int MIN_COL=20;
  110. int MAX_DIST=50;
  111.  
  112. void drawpol1( VERTEX_3D *pol, int lados )
  113. {   int mxcnt, mxc, mny, mxy, cuenta, sgn, ptr, offs;
  114.     int x1,y1,z1,x2,y2,z2, NUM_COL;
  115.     long d_col, r_col;
  116.     char far *SCR;
  117.  
  118.     NUM_COL=MAX_COL-MIN_COL;
  119.  
  120.     d_col=(long)NUM_COL;
  121.     d_col<<=16;
  122.     d_col/=(long)MAX_DIST;
  123.  
  124.     //Cerrar el polígono
  125.     asm{
  126.         cld
  127.         les di,pol
  128.         mov bx,lados
  129.         mov ax,bx
  130.         shl bx,2
  131.         shl ax,1
  132.         add bx,ax
  133.         mov eax,es:di
  134.         mov es:[di+bx],eax
  135.         mov ax,es:[di+4]
  136.         add bx,4
  137.         mov es:[di+bx],ax
  138.     };
  139.  
  140.     //Obtener y máxima y mínima
  141.     for( cuenta=1, mny=mxy=0; cuenta<4; cuenta++)
  142.     {
  143.         if(pol[mny].y>pol[cuenta].y)
  144.             mny=cuenta;
  145.  
  146.         if(pol[mxy].y<pol[cuenta].y)
  147.             mxy=cuenta;
  148.     };
  149.  
  150.     if( mny==mxy )  //si la altura del polígono es cero, salir
  151.         return;
  152.  
  153.     mxcnt=pol[mxy].y-pol[mny].y;
  154.  
  155. BACKWD:
  156.     ptr=mny;
  157.     cuenta=0;
  158.     do{
  159.         if(ptr<=0)
  160.             ptr=lados;
  161.  
  162.         int y1=pol[ptr].y;
  163.         int y2=pol[ptr-1].y;
  164.  
  165.         int x1=pol[ptr].x;
  166.         int x2=pol[ptr-1].x;
  167.  
  168.         sgn=1;
  169.         long delta=(long)x2;
  170.         delta-=(long)x1;
  171.         if(delta<0L)
  172.         {
  173.             delta=-delta;
  174.             sgn=-1;
  175.         };
  176.  
  177.         long delta1=(long)y2;
  178.         delta1-=(long)y1;
  179.         if(delta1==0)
  180.         {
  181.             ptr--;
  182.             continue;
  183.         };
  184.         delta<<=16;
  185.         delta/=delta1;
  186.         delta1=(long)x1;
  187.         delta1<<=16;
  188.  
  189.         while(y1<y2)
  190.         {
  191.             x1=(int)(delta1>>16);
  192.  
  193.             x_array[cuenta]=x1;
  194.             if(sgn<0)
  195.                 delta1-=delta;
  196.             else
  197.                 delta1+=delta;
  198.             y1++;
  199.             cuenta+=2;
  200.         };
  201.         ptr--;
  202.     }while(ptr!=mxy);
  203.  
  204. FORWD:
  205.     ptr=mny;
  206.     cuenta=1;
  207.         if(ptr>=lados)
  208.             ptr=0;
  209.  
  210.     do{
  211.  
  212.         int y1=pol[ptr].y;
  213.         int y2=pol[ptr+1].y;
  214.  
  215.         int x1=pol[ptr].x;
  216.         int x2=pol[ptr+1].x;
  217.  
  218.         sgn=1;
  219.         long delta=(long)x2;
  220.         delta-=(long)x1;
  221.         if(delta<0L)
  222.         {
  223.             delta=-delta;
  224.             sgn=-1;
  225.         };
  226.  
  227.         long delta1=(long)y2;
  228.         delta1-=(long)y1;
  229.  
  230.         if(delta1==0)
  231.         {
  232.             ptr++;
  233.             continue;
  234.         };
  235.         delta<<=16;
  236.         delta/=delta1;
  237.         delta1=(long)x1;
  238.         delta1<<=16;
  239.  
  240.         while(y1<y2)
  241.         {
  242.             x1=(int)(delta1>>16);
  243.  
  244.             x_array[cuenta]=x1;
  245.             if(sgn<0)
  246.                 delta1-=delta;
  247.             else
  248.                 delta1+=delta;
  249.             y1++;
  250.             cuenta+=2;
  251.         };
  252.         ptr++;
  253.         if(ptr>=lados)
  254.             ptr=0;
  255.  
  256.     }while(ptr!=mxy);
  257.  
  258. SHADE_1:
  259.  
  260.     ptr=mny;
  261.     cuenta=0;
  262.     do{
  263.         if(ptr<=0)
  264.             ptr=4;
  265.  
  266.         int y1=pol[ptr].y;
  267.         int y2=pol[ptr-1].y;
  268.  
  269.         int z1=pol[ptr].z;
  270.         int z2=pol[ptr-1].z;
  271.  
  272.         sgn=1;
  273.         long delta=(long)z2;
  274.         delta-=(long)z1;
  275.         if(delta<0L)
  276.         {
  277.             delta=-delta;
  278.             sgn=-1;
  279.         };
  280.  
  281.         long delta1=(long)y2;
  282.         delta1-=(long)y1;
  283.         if(delta1==0)
  284.         {
  285.             ptr--;
  286.             continue;
  287.         };
  288.         delta<<=16;
  289.         delta/=delta1;
  290.         delta1=(long)z1;
  291.         delta1<<=16;
  292.  
  293.         while(y1<y2)
  294.         {
  295.             z1=(int)(delta1>>16);
  296.             r_col=(long)z1 * d_col;
  297.  
  298.             if( r_col>((long)MAX_COL<<16))
  299.                 r_col=(long)(MAX_COL<<16);
  300.             if( r_col<0 )
  301.                 r_col=0;
  302.  
  303.             colr[cuenta]=(int)(r_col>>16);
  304.  
  305.             if(sgn<0)
  306.                 delta1-=delta;
  307.             else
  308.                 delta1+=delta;
  309.             y1++;
  310.             cuenta+=2;
  311.         };
  312.         ptr--;
  313.     }while(ptr!=mxy);
  314.  
  315. SHADE_2:
  316.     ptr=mny;
  317.     cuenta=1;
  318.     do{
  319.         if(ptr>=(4))
  320.             ptr=0;
  321.  
  322.         int y1=pol[ptr].y;
  323.         int y2=pol[ptr+1].y;
  324.  
  325.         int z1=pol[ptr].z;
  326.         int z2=pol[ptr+1].z;
  327.  
  328.         sgn=1;
  329.         long delta=(long)z2;
  330.         delta-=(long)z1;
  331.         if(delta<0L)
  332.         {
  333.             delta=-delta;
  334.             sgn=-1;
  335.         };
  336.  
  337.         long delta1=(long)y2;
  338.         delta1-=(long)y1;
  339.         if(delta1==0)
  340.         {
  341.             ptr++;
  342.             continue;
  343.         };
  344.         delta<<=16;
  345.         delta/=delta1;
  346.         delta1=(long)z1;
  347.         delta1<<=16;
  348.  
  349.         while(y1<y2)
  350.         {
  351.             z1=(int)(delta1>>16);
  352.             r_col=(long)z1 * d_col;
  353.  
  354.             if( r_col>((long)MAX_COL<<16))
  355.                 r_col=(long)(MAX_COL<<16);
  356.             if( r_col<0 )
  357.                 r_col=0;
  358.  
  359.             colr[cuenta]=(int)(r_col>>16);
  360.  
  361.             if(sgn<0)
  362.                 delta1-=delta;
  363.             else
  364.                 delta1+=delta;
  365.             y1++;
  366.             cuenta+=2;
  367.         };
  368.         ptr++;
  369.     }while(ptr!=mxy);
  370.  
  371. RENDER:
  372.  
  373.     SCR=(char far *)MK_FP( SCRN, 0 );
  374.     y2=pol[mny].y;
  375.  
  376.     for( y1=0; y1<mxcnt; y1++ )
  377.     {
  378.         x1=x_array[y1*2];
  379.         x2=x_array[y1*2+1];
  380.         r_col=(long)(colr[y1*2]);
  381.         d_col=(long)(colr[y1*2+1]);
  382.         d_col-=r_col;
  383.         if(d_col<0L)
  384.         {
  385.             d_col=-d_col;
  386.             sgn=1;
  387.         }
  388.         else
  389.         sgn=-1;
  390.  
  391.         d_col<<=16;
  392.         long delta=(x2-x1);
  393.         if(delta!=0)
  394.             d_col/=delta;
  395.         else
  396.             d_col=0;
  397.         offs=y_off[y2];
  398.         while(x1!=x2)
  399.         {
  400.             SCR[offs+x1]=(int)(r_col>>16);
  401.             r_col+=d_col;
  402.             x1++;
  403.         };
  404.     };
  405. }
  406.  
  407. /*  FUNCIαN: _drawpoly
  408.     Dibuja polígonos llenos, sólo polígonos convexos.
  409.     parámetros:
  410.     pol:    arreglo secuencial x, y, x, y, de enteros
  411.     lados:    Numero de lados del polígono
  412.     color:    Color del polígono
  413. */
  414. void drawpoly( int far *pol, int lados, int color)
  415. {   int mxc, mny, mxy, index, cuenta, mxcnt, scrn, DC, min,
  416.             min2, max;
  417.     long color1;
  418.  
  419.     //Proteger el puntero de pantalla
  420.     scrn=SCRN;
  421.     DC=0;
  422.     //Cerrar el polígono
  423.     asm{
  424.         cld
  425.         mov es,closed
  426.         mov cx,lados
  427.         push ds
  428.         lds si,pol
  429.         xor di,di
  430.         rep movsd
  431.         lds si,pol
  432.         movsd
  433.     };
  434.  
  435.     //Obtener y máxima y mínima
  436.     for( cuenta=3, mny=mxy=1; cuenta<=(lados*2); cuenta+=2)
  437.     {
  438.         if(closed_ptr[mny]>closed_ptr[cuenta])
  439.             mny=cuenta;
  440.  
  441.         if(closed_ptr[mxy]<closed_ptr[cuenta])
  442.             mxy=cuenta;
  443.     };
  444.  
  445.     if( mny==mxy )
  446.         return;
  447.  
  448.     min=closed_ptr[mny];
  449.     if(min<0)
  450.         min=-min;
  451.     else
  452.         min=0;
  453.     min2=min;
  454.     max=closed_ptr[mxy];
  455.     if(max>319)
  456.         max=319;
  457.     if(max<0)
  458.         return;
  459.  
  460.     mxcnt=closed_ptr[mxy]-closed_ptr[mny];
  461.  
  462.     asm{
  463.         mov ax,mny   //mny para que apunte a la x en bytes
  464.         add ax,ax
  465.         sub ax,2
  466.         mov mny,ax
  467.         mov ax,mxy  //mxy para que apunte a la x en bytes
  468.         add ax,ax
  469.         sub ax,2
  470.         mov mxy,ax
  471.         mov ax,lados //mxc a un valor en bytes, para comparación.
  472.         add ax,ax
  473.         add ax,ax
  474.         mov mxc,ax
  475.     };
  476.  
  477. BACKWD:
  478.     asm{
  479.         push ds             //proteger el segmento
  480.         les di,x_array
  481.         lds si,closed_ptr//cargar los punteros: (origen=pol; destino=x_array)
  482.         mov si,mny
  483.     };
  484. label0:
  485.     asm{
  486.         cmp si,4     //si SI está en el límite inferior, continuar arriba
  487.         jge index1
  488.         mov si,mxc
  489.         cmp si,mxy
  490.         jne index1
  491.         jmp salida1
  492.     };
  493. index1:
  494.     asm{
  495.         mov ax,[si]  //cargar X y Y para obtener offset, proteger a la
  496.         mov bx,[si+2]//vez sus valores para uso posterior
  497.         mov dx,ax
  498.         mov cx,bx
  499.         push ds ax
  500.         mov ax,seg y_off
  501.         mov ds,ax
  502.         add bx,bx
  503.         pop ax
  504.         add ax,[offset y_off + bx ]
  505.         xor bx,bx    // para uso posterior de bx como indicador de signo
  506.         pop ds
  507.         push ax        //proteger el valor del offset
  508.         sub dx,[si-4]//obtener el valor delta
  509.         jns pos_1a
  510.         xor bx,1
  511.         neg dx
  512.     };
  513. pos_1a:
  514.     asm{
  515.         sub cx,[si-2]
  516.         neg cx        //corregir la resta negativa
  517.         add word ptr DC,cx
  518.         cmp word ptr DC,320
  519.         jbe no_jmp1
  520.         jmp salida_p
  521.     };
  522. no_jmp1:
  523.     asm{
  524.         mov ax,dx
  525.         shl eax,16
  526.         movsx ecx,cx
  527.         xor edx,edx
  528.         jcxz y_es_cero1    //Evitar división por cero
  529.         idiv ecx
  530.         jmp y_no_es_cero1
  531.     };
  532. y_es_cero1:
  533.     asm{
  534.         pop ax
  535.         sub si,4
  536.         cmp si,mxy
  537.         jne label0
  538.         jmp salida1
  539.     };
  540. y_no_es_cero1:
  541.     asm{
  542.         rol eax,16    //convertirlo en una variable flotante para su uso
  543.         mov edx,eax
  544.         xor eax,eax
  545.         pop ax        //recuperar el offset
  546.         cmp word ptr min,0
  547.         jnz dummy1
  548.         or bx,bx
  549.         jz label1a
  550.     };
  551. label1:
  552.     asm{
  553.         mov es:di,ax//poner el offset en la variable
  554.         add di,4
  555.         add eax,edx
  556.         adc ax,320  //calcular el nuevo offset
  557.         loop label1 //hasta terminar con el valor y2-y
  558.         sub si,4
  559.         cmp si,mxy
  560.         je no_jmp1b
  561.         jmp label0
  562.     };
  563. no_jmp1b:
  564.     asm{
  565.         jmp salida1
  566.     };
  567. label1a:
  568.     asm neg dx
  569. label1b:
  570.     asm{
  571.         mov es:di,ax//poner el offset en la variable
  572.         add di,4
  573.         add eax,edx
  574.         sbb ax,-320  //calcular el nuevo offset
  575.         loop label1b//hasta terminar con el valor y2-y
  576.         sub si,4
  577.         cmp si,mxy
  578.         je salida1
  579.         jmp label0
  580.     };
  581. dummy1:
  582.  
  583.  
  584. salida1:
  585. FORWD:
  586.     asm{
  587.         mov word ptr DC,0
  588.         mov di,2
  589.         mov si,mny
  590.     };
  591. label02:
  592.     asm{
  593.         cmp si,mxc     //si SI está en el límite inferior, continuar arriba
  594.         jl index12
  595.         mov si,0
  596.         cmp si,mxy
  597.         jne index12
  598.         jmp salida12
  599.     };
  600. index12:
  601.     asm{
  602.         mov ax,[si]  //cargar X y Y para obtener offset, proteger a la
  603.         mov bx,[si+2]//vez sus valores para uso posterior
  604.         mov dx,ax
  605.         mov cx,bx
  606.         push ds ax
  607.         mov ax,seg y_off
  608.         mov ds,ax
  609.         add bx,bx
  610.         pop ax
  611.         add ax,[offset y_off + bx ]
  612.         xor bx,bx    // para uso posterior de bx como indicador de signo
  613.         pop ds
  614.         push ax      //proteger el valor del offset
  615.         sub dx,[si+4]//obtener el valor delta
  616.         jns pos_1a2
  617.         xor bx,1
  618.         neg dx
  619.     };
  620. pos_1a2:
  621.     asm{
  622.         sub cx,[si+6]
  623.         jns pos2
  624.         neg cx
  625.     };
  626. pos2:
  627.     asm{
  628.         add word ptr DC,cx
  629.         cmp word ptr DC,320
  630.         jne no_jmp2
  631.         jmp salida_p
  632.     };
  633. no_jmp2:
  634.     asm{
  635.         mov ax,dx
  636.         shl eax,16
  637.         movsx ecx,cx
  638.         xor edx,edx
  639.         jcxz y_es_cero12//Evitar división por cero
  640.         idiv ecx
  641.         jmp y_no_es_cero12
  642.     };
  643. y_es_cero12:
  644.     asm{
  645.         pop ax
  646.         add si,4
  647.         cmp si,mxy
  648.         jne label02
  649.         jmp salida12
  650.     };
  651. y_no_es_cero12:
  652.     asm{
  653.         rol eax,16  //convertirlo en una variable flotante para su uso
  654.         mov edx,eax
  655.         pop ax      //recuperar el offset
  656.         or bx,bx
  657.         jz label1a2
  658.     };
  659. label12:
  660.     asm{
  661.         mov es:di,ax //guardar el offset primero
  662.         add di,4    //calcular el siguiente
  663.         add eax,edx
  664.         adc ax,320
  665.         sub cx,1 //hasta terminar con el valor y2-y
  666.         jz term2a
  667.         mov es:di,ax
  668.         add di,4
  669.         add eax,edx
  670.         adc ax,320  //calcular el nuevo offset
  671.         loop label12 //hasta terminar con el valor y2-y
  672.     };
  673. term2a:
  674.     asm{
  675.         add si,4
  676.         cmp si,mxy
  677.         je no_jmp
  678.         jmp label02
  679.     };
  680. no_jmp:
  681.     asm    jmp salida12
  682.  
  683. label1a2:
  684.     asm neg dx
  685. label1b2:
  686.     asm{
  687.         mov es:di,ax//guardar el offset primero
  688.         add di,4     //calcular el nuevo offset
  689.         add eax,edx
  690.         sbb ax,-320
  691.         sub cx,1
  692.         jz term2b
  693.         mov es:di,ax//guardar el offset primero
  694.         add di,4     //calcular el nuevo offset
  695.         add eax,edx
  696.         sbb ax,-320
  697.         loop label1b2//hasta terminar con el valor y2-y
  698.     };
  699. term2b:
  700.     asm{
  701.         add si,4
  702.         cmp si,mxy
  703.         je salida12
  704.         jmp label02
  705.     };
  706. salida12:
  707. DRAW:
  708.     asm{
  709.         mov ax,color
  710.         mov ah,al
  711.         mov bx,ax
  712.         shl eax,16
  713.         mov ax,bx
  714.         mov color1,eax
  715.         mov si,es
  716.         mov ds,si
  717.         xor si,si
  718.         mov ax,scrn
  719.         mov es,ax
  720.         mov bx,mxcnt
  721.         and bx,255
  722.     }
  723. loop_p2:
  724.     asm{
  725.         lodsd
  726.         mov di,ax
  727.         shr eax,16
  728.         mov dx,ax
  729.         cmp di,dx
  730.         jz next
  731.         jb norm_p
  732.         xchg dx,di
  733.     };
  734. norm_p:
  735.     asm{
  736.         sub dx,di
  737.         and dx,1023
  738.         jns pos_p
  739.         neg dx
  740.     };
  741. pos_p:
  742.     asm{
  743.         mov eax,color1
  744.         cmp dx,4
  745.         jle menos_de_una_linea
  746.         mov cx,di
  747.         and cx,3
  748.         sub dx,cx
  749.         rep stosb
  750.         mov cx,dx
  751.         shr cx,2
  752.         rep stosd
  753.         and dx,3
  754.     };
  755. menos_de_una_linea:
  756.     asm{
  757.         mov cx,dx
  758.         rep stosb
  759.     };
  760. next:
  761.     asm{
  762.         sub bx,1
  763.         jnz loop_p2
  764.     };
  765. salida_p:
  766.     asm{
  767.         pop ds
  768.     };
  769. }
  770.  
  771. void box( int x1, int y1, int w, int h, int color, int segm )
  772. {
  773.     asm{
  774.         mov ax,x1
  775.         mov bx,y1
  776.     }
  777.     getoff();
  778.     asm{
  779.         mov di,ax
  780.         mov ax,segm
  781.         mov es,ax
  782.         mov si,w
  783.         mov bx,h
  784.         mov ax,color
  785.         mov dx,320
  786.         sub dx,si
  787.     };
  788. looper:
  789.     asm{
  790.         mov cx,si
  791.         rep stosb
  792.         sub bx,1
  793.         jz salida
  794.         add di,dx
  795.         jmp looper
  796.     };
  797. salida:
  798. }
  799.  
  800.  
  801. //*************************VIDEO, BAJO NIVEL***************************
  802. //    FUNCION: setvmode
  803. //    ajusta el modo de video al especificado
  804. //    parámetros:    vmode - Modo de video
  805. //    retorna:    nada significativo.
  806. //    destruye:    AX.
  807.  
  808. void setvmode( int v_mode )
  809. {
  810.     asm{
  811.     mov ax,v_mode
  812.     sub ah,ah
  813.     int 10h
  814.     };
  815. }
  816.  
  817. //    FUNCION: getvmode
  818. //    obtiene del sistema el modo de video actual
  819. //    parámetros:        NINGUNO.
  820. //    retorna:        Modo de video en AX.
  821. //    destruye:        AX
  822.  
  823. int getvmode( void )
  824. {
  825.     asm{
  826.     mov ah,0Fh
  827.     int 10h
  828.     xor ah,ah
  829.     };
  830.     return _AX;
  831. }
  832.  
  833. //************************TRAZOS GEOMÉTRICOS***************************
  834. void drawvline(void)
  835. {   // comunicación por registro
  836.     // color en ax, yi en bx, yf en cx, x en dx
  837.     asm{
  838.     sub cx,bx
  839.     shl bx,1
  840.     mov di,[bx+offset y_off]
  841.     add di,dx
  842.     mov dx,0A000h
  843.     mov es,dx
  844.     };
  845. dvl1:
  846.     asm{
  847.     mov es:[di],al
  848.     add di,320
  849.     loop dvl1
  850.     };
  851. }
  852.  
  853. //*************************** MISCELANEOS ******************************
  854.  
  855. //    FUNCIαN: valloc
  856. //    reserva memoria a través de farmalloc, alinea el bloque a cero
  857. //    y retorna sólo el segmento
  858. //    parámetros: _asize - Tamaño del bloque pedido
  859. //    retorna:
  860. //        éxito:segmento del bloque alineado
  861. //        error:CARRY y cero
  862.  
  863. int valloc( unsigned long asize )
  864. {   unsigned long size;
  865.     asm{
  866.     mov eax,asize
  867.     add eax,16
  868.     mov size,eax
  869.     };
  870.     farmalloc( size );
  871.     return _DX+1;
  872. }
  873.  
  874. //    FUNCIαN: _vfree
  875. //    libera un bloque de memoria reservado por _valloc
  876. //    parámetros:    segm, el segmento en cuestión
  877. //    retorna lo mismo que farfree de alloc.h en Turbo c
  878.  
  879. void vfree( unsigned int segm )
  880. {   int result;
  881.     void far *pointer;
  882.  
  883.     asm{
  884.     mov ax,segm
  885.     dec ax
  886.     rol eax,16
  887.     mov ax,4
  888.     mov dword ptr pointer,eax
  889.     };
  890.     farfree( pointer );
  891. }
  892.  
  893. void initclosed( void )
  894. {
  895.     closed=valloc(2000);
  896.     if(closed==1)
  897.     {
  898.         setvmode(old_mode);
  899.         printf("\nMemoria insuficiente: error 2.");
  900.             exit(0);
  901.     };
  902.     w_array=closed+8;
  903.     x_array=(int far *)MK_FP( w_array, 0 );
  904.     closed_ptr=(int far *)MK_FP( closed, 0 );
  905. }
  906.  
  907. //    FUNCIαN: getoff
  908. //    retorna el offset de las coordenadas (para una pantalla de 320 x 200)
  909. //    parámetros:    AX: coordenada X
  910. //                BX: coordenada Y
  911. //    retorna:
  912. //        éxito:    AX: offset
  913.  
  914. int getoff( void )
  915. {
  916.     asm{
  917.     push ds ax
  918.     mov ax,seg y_off
  919.     mov ds,ax
  920.     add bx,bx
  921.     pop ax
  922.     add ax,[offset y_off + bx ]
  923.     pop ds
  924.     };
  925.     return _AX;
  926. }
  927.  
  928. //************************ MANEJO DE BITMAPS ***************************
  929. //    FUNCIαN: _getimage
  930. //    recupera una imagen de una pantalla virtual, reserva suficiente memoria
  931. //    y la pone en el formato BGI ( dos palabras x_length y y_length y
  932. //    porteriormente los datos en 8 bits por pixel )
  933. //    parámetros:
  934. //    se pasan por medio de la estructura gi_struc
  935. //    gi_orig:segmento en que se encuentra la pantalla virtual de la que
  936. //            se toma la imágen
  937. //    gi_xo, gi_yo:    X y Y superior izq. del origen
  938. //    gi_wo:        anchura de la imágen, en pixels
  939. //    gi_ho:        altura de la imágen en pixels
  940. //    gi_xd, gi_yd:    X y Y superior izq. del destino
  941. //    las demás son variables internas y se sobreescriben al llamar a la función
  942. //    retorna:    AX: el segmento en que se colocó la imágen
  943. //
  944.  
  945. int getimage( int orig, int xo, int yo, int wo, int ho )
  946. {    int delta, gi_seg;
  947.     asm{
  948.     mov ax,xo
  949.     mov bx,yo
  950.     };
  951.     getoff();
  952.     asm{
  953.     mov si,ax            //guardar en si
  954.     mov ax,wo    //calcular el tamaño de la imágen
  955.     mov cx,ho
  956.     mul cx
  957.     add ax,4
  958.     cwde
  959.     };
  960.     valloc( _EAX );    //reservar memoria suficiente para ella
  961.     asm{
  962.     mov es,ax
  963.     mov gi_seg,ax
  964.     mov di,4
  965.     mov ax,wo
  966.     mov es:[0],ax
  967.     mov ax,ho
  968.     mov es:[2],ax
  969.     mov dx,320
  970.     sub dx,wo
  971.     mov delta,dx
  972.     mov ax,ds
  973.     mov fs,ax
  974.     mov ax,ho
  975.     shl ax,8
  976.     mov cx,wo
  977.     mov dx,cx
  978.     mov bx,delta
  979.     mov ds,orig
  980.     };
  981. gi_lineas:
  982.     asm{
  983.     rep movsb
  984.     dec ah
  985.     jz gi_sal
  986.     add si,bx
  987.     mov cx,dx
  988.     jmp gi_lineas
  989.     };
  990. gi_sal:
  991.     asm{
  992.     mov dx,fs
  993.     mov ds,dx
  994.     };
  995.     return gi_seg;
  996. }
  997.  
  998. //    FUNCIαN: _putimage
  999. //    pone en la pantalla especificada, la imágen pedida en modo PUT,
  1000. //    como su nombre lo indica
  1001. //    parámetros:    ctrl_struc - puntero a la estructura de control 'objeto'
  1002. //                vsh           - vs_handle de la pantalla destino
  1003. //    retorna:    nada significativo
  1004. //
  1005.  
  1006. void putimage( int far *ctrl_struc, int dest )
  1007. {    int orig;
  1008.     asm{
  1009.     push ds
  1010.     lfs bx,ctrl_struc       //segmento del struc de control
  1011.     mov ax,fs:[bx]      //segmento orígen
  1012.     mov orig,ax             //guardar en orig
  1013.     mov ax,fs:[bx+2]
  1014.     mov bx,fs:[bx+4]
  1015.     };
  1016.     getoff();
  1017.     asm{            //offset del punto de inicio
  1018.     mov di,ax
  1019.     mov ax,dest              //handle de la pantalla destino
  1020.     mov es,ax
  1021.     mov ds,orig             //cargar en fs el segmento de orígen
  1022.     mov si,4
  1023.     mov bx,ds:0
  1024.     mov dx,320
  1025.     sub dx,bx
  1026.     push bp
  1027.     mov bp,ds:[2]
  1028.     };
  1029. lineas:
  1030.     asm{
  1031.     mov cx,bx
  1032.     rep movsb
  1033.     add di,dx
  1034.     dec bp
  1035.     jnz lineas
  1036.     pop bp
  1037.     pop ds
  1038.     };
  1039. }
  1040.  
  1041. //    FUNCIαN: _drwimage
  1042. //    pone en la pantalla especificada, la imágen pedida, pero considera
  1043. //  al color negro como transparente
  1044. //    parámetros:    ctrl_struc - puntero a la estructura de control 'objeto'
  1045. //                vsh           - vs_handle de la pantalla destino
  1046. //    retorna:    nada significativo
  1047. //
  1048.  
  1049. void drwimage( int far *ctrl_struc, int dest )
  1050. {    int orig;
  1051.     asm{
  1052.     push ds
  1053.     lfs bx,ctrl_struc       //segmento del struc de control
  1054.     mov ax,fs:[bx]      //segmento orígen
  1055.     mov orig,ax             //guardar en orig
  1056.     mov ax,fs:[bx+2]
  1057.     mov bx,fs:[bx+4]
  1058.     };
  1059.     getoff();
  1060.     asm{            //offset del punto de inicio
  1061.     mov di,ax
  1062.     mov ax,dest              //handle de la pantalla destino
  1063.     mov es,ax
  1064.     mov ds,orig             //cargar en fs el segmento de orígen
  1065.     mov si,4
  1066.     mov bx,ds:0
  1067.     mov dx,320
  1068.     sub dx,bx
  1069.     push bp
  1070.     mov bp,ds:[2]
  1071.     }
  1072. di_lineas:
  1073.     asm mov cx,bx
  1074. di_loop:
  1075.     asm{
  1076.     mov al,ds:[si]
  1077.     or al,al
  1078.     jz nocolor
  1079.     mov es:[di],al
  1080.     };
  1081. nocolor:
  1082.     asm{
  1083.     inc di
  1084.     inc si
  1085.     loop di_loop
  1086.     add di,dx
  1087.     dec bp
  1088.     jnz di_lineas
  1089.     pop bp
  1090.     pop ds
  1091.     };
  1092. }
  1093.  
  1094. //    FUNCIαN: scale
  1095. //    escala un bitmap al tamaño especificado
  1096. //    parámetros:
  1097. //   se pasan a través de la estructura de control scl_struc:
  1098. //   variable  tamaño
  1099. //    scl_orig    dd  puntero sg:of de la imágen origen y destino
  1100. //    scl_dest    dd
  1101. //    scl_orw        dw    ancho y alto de la imágen origen
  1102. //    scl_orh        dw
  1103. //    scl_dsw        dw  ancho y alto de la imágen destino
  1104. //    scl_dsh     dw
  1105. //    scl_deltaw  dd    variables internas
  1106. //    scl_deltah    dd
  1107. //    scl_psi        dw
  1108. //
  1109.  
  1110. int scale(char far *orig, char far *dest, int orw, int orh, int dsw, int dsh )
  1111. {    long deltaw, deltah;
  1112.     int psi;
  1113.  
  1114.     asm{
  1115.     mov dx,dsw
  1116.     xor ax,ax
  1117.     mov bx,orw
  1118.     div bx
  1119.     mov word ptr deltaw,ax
  1120.     mov word ptr deltaw[2],dx
  1121.     mov dx,dsh
  1122.     xor ax,ax
  1123.     mov bx,orh
  1124.     div bx
  1125.     mov word ptr deltah,ax
  1126.     mov word ptr deltah[2],dx
  1127.     lds si,orig
  1128.     les di,dest
  1129.     mov edx,deltaw
  1130.     rol edx,16
  1131.     mov ebx,deltah
  1132.     rol ebx,16
  1133.     mov cx,bx
  1134.     mov ax,0FFFFh
  1135.     sub ax,dsh
  1136.     shl eax,16
  1137.     mov ax,0FFFFh
  1138.     };
  1139. linea:
  1140.     asm mov psi,si
  1141.     asm mov cx,dsw
  1142. pixel:
  1143.     asm{
  1144.     add esi,edx
  1145.     adc esi,0
  1146.     movsb
  1147.     dec si
  1148.     loop pixel
  1149.     add eax,10000h
  1150.     jc scl_salida
  1151.     mov si,psi
  1152.     add ecx,ebx
  1153.     adc cx,0
  1154.     };
  1155. mult:
  1156.     asm{
  1157.     add si,orw
  1158.     loop mult
  1159.     jmp linea
  1160.     };
  1161. scl_salida:
  1162.     return 0;
  1163. }
  1164.  
  1165. //*********************** PANTALLAS COMPLETAS ****************************
  1166.  
  1167. //    FUNCIαN: clear
  1168. //    borra la pantalla especificada al color deseado
  1169. void clear( int c_color, int segm )
  1170. {
  1171.     asm{
  1172.     mov ax,c_color
  1173.     mov bx,segm
  1174.     mov es,bx
  1175.     mov ah,al
  1176.     mov bx,ax
  1177.     rol eax,16
  1178.     mov ax,bx
  1179.     mov di,0
  1180.     mov cx,16100
  1181.     rep stosd
  1182.     };
  1183. }
  1184.  
  1185. //    FUNCIαN: flip
  1186. //    pasa el contenido de una pantalla a otra
  1187. //    parámetros: orig - vs_handle de la pantalla orígen
  1188. //                   dest - vs_handle de la pantalla destino
  1189.  
  1190. void flip( int orig, int dest )
  1191. {
  1192.     asm{
  1193.     mov cx,16100
  1194.     xor si,si
  1195.     mov di,si
  1196.     push ds
  1197.     mov es,dest
  1198.     mov ds,orig
  1199.     rep movsd
  1200.     pop ds
  1201.     };
  1202. }
  1203.  
  1204. //    FUNCIαN: putblock
  1205. //    toma un bloque de una pantalla y lo pasa a otra
  1206. //    parámetros:
  1207. //    se pasan a través de la función pb_struc
  1208. //    orig:segmento de origen
  1209. //    orig: "  "    "  destino
  1210. //    xo:    X de la esquina superior izquierda del rectángulo de origen
  1211. //    yo:    Y
  1212. //    wo:    anchura del orígen en pixels
  1213. //    ho:    altura
  1214. //    xd:    X de la esquina superior izquierda del rectángulo destino
  1215. //    yd:    Y
  1216. //    las otras variables del struc son variables internas que se sobreescriben
  1217. //    cada vez que se llama la función
  1218. //    retorna:    nada significativo
  1219.  
  1220. void putblock( int orig,int dest,int xo,int yo,int wo,int ho,int xd,int yd)
  1221. {    int o_of, d_of;
  1222.     asm{
  1223.     push ds
  1224.     mov  ax,xo   //offset del origen
  1225.     mov bx,yo
  1226.     };
  1227.     getoff();
  1228.     asm{
  1229.     mov si,ax
  1230.     mov ax,xd   //offset del destino
  1231.     mov bx,yd
  1232.     };
  1233.     getoff();
  1234.     asm{
  1235.     mov di,ax
  1236.     mov bx,wo
  1237.     mov dx,320
  1238.     sub dx,bx
  1239.     shr bx,2
  1240.     jc pb_lineas8
  1241.     mov ds,orig
  1242.     mov es,dest
  1243.     push bp
  1244.     mov bp,ho
  1245.     };
  1246. pb_lineas:
  1247.     asm{
  1248.     mov cx,bx
  1249.     rep movsd
  1250.     add si,dx
  1251.     add di,dx
  1252.     dec bp
  1253.     jnz pb_lineas
  1254.     pop bp
  1255.     pop ds
  1256.     jmp salida
  1257.     };
  1258. pb_lineas8:
  1259.     asm{
  1260.     mov bx,wo
  1261.     mov ds,orig
  1262.     mov es,dest
  1263.     push bp
  1264.     mov bp,ho
  1265.     };
  1266. pb_looper:
  1267.     asm{
  1268.     mov cx,bx
  1269.     rep movsb
  1270.     add si,dx
  1271.     add di,dx
  1272.     dec bp
  1273.     jnz pb_looper
  1274.     pop bp
  1275.     pop ds
  1276.     };
  1277. salida:
  1278. }
  1279.  
  1280. //    función: scroll_up
  1281. //pone dos segmentos de una pantalla, en la otra
  1282. //    argumentos:    orig - segmento de origen
  1283. //                dest - segmento destino
  1284. //                part - linea de partición
  1285. //    retorna: nada significativo
  1286. //    destruye todos los registros
  1287.  
  1288. void scroll_up( int orig, int dest, int part)
  1289. {
  1290.     asm{
  1291.     mov es,dest
  1292.     mov ds,orig
  1293.     mov bx,part
  1294.     add bx,part
  1295.     mov si,[bx+offset y_off]
  1296.     mov dx,si
  1297.     mov cx,64000
  1298.     sub cx,si
  1299.     sub di,di
  1300.     or cx,cx
  1301.     jz nothing1
  1302.     shr cx,1
  1303.     jnc su_nocarry1
  1304.     jz nothing1
  1305.     stosb
  1306.     };
  1307. su_nocarry1:
  1308.     asm{
  1309.     shr cx,1
  1310.     jnc su_nocarry2
  1311.     jz nothing1
  1312.     stosw
  1313.     };
  1314. su_nocarry2:
  1315.     asm rep movsd
  1316. nothing1:
  1317.     asm{
  1318.     sub si,si
  1319.     mov cx,dx
  1320.     or cx,cx
  1321.     jz nothing2
  1322.     shr cx,1
  1323.     jnc su_nocarry3
  1324.     jz nothing2
  1325.     stosb
  1326.     };
  1327. su_nocarry3:
  1328.     asm{
  1329.     shr cx,1
  1330.     jnc su_nocarry4
  1331.     jz nothing2
  1332.     stosw
  1333.     };
  1334. su_nocarry4:
  1335.     asm rep movsd
  1336. nothing2:
  1337.     asm pop ds
  1338. }
  1339.  
  1340.